/*
* Class: RssFeedStreamParser
* Description: Class is used to parse data from the url of an rss feed. It is mainly
* used by RssFeedFactory to create RssFeed Objects.
*
* Note:
* Date: March 28, 2012
* Author: Shane Swayney
*/


package rssreaderapp;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;


/**
 * Class is used to parse data from the url of an rss feed. It is mainly
 * used by {@link RssFeedFactory} to create {@link RssFeed} Objects.
 * 
 * @author Shane Swayney <shane.swayney@gmail.com>
 */
public class RssFeedStreamParser {
    
    //Variables
    private String rssFeedURL = "";
    InputStream input = null;
    private XMLEventReader xmlEventReader = null;
    /**
     * Enum for type save parameters in {@link getNextTextByTag}
     */
    public static enum RSSFEEDTAGS {TITLE,URL,DISCRIPTION,PUBDATE,LINK,LASTPUBDATE}
    
     /**
     * Private constructor to prevent calls to open method without setting a url first
     */
    private RssFeedStreamParser(){};
    
    /**
     * Constructor to create a RssFeedStreamParser from a url 
     * @param urlFile
     */
    public RssFeedStreamParser(String urlFile)
    {
        rssFeedURL = urlFile;
    };

    /**
     * Sets the String containing the url to an rss feed file
     * 
     * @param urlFile
     */
    public void setURL(String urlFile){
        rssFeedURL = urlFile;
    }
    
    
    /**
     * Method to open the url for parsing. Throws exceptions to be caught by
     * {@link RssReaderFrame} to it can output a relevant response to
     * bad url links etc. 
     * 
     * Note: Method does not check that the url has not be set. However, the
     * default constructor is private. This will be fixed in version 2.
     * 
     * @throws MalformedURLException
     * @throws IOException
     * @throws XMLStreamException
     */
    public void openStream() throws MalformedURLException, IOException, XMLStreamException 
    {
        //If the streams are all ready active, close them
        if((xmlEventReader != null) || (input != null))
        {this.closeStream();}

        //opean the steam for parsing
         XMLInputFactory inputFactory = XMLInputFactory.newInstance();
         input = new URL(rssFeedURL).openStream();
         xmlEventReader = inputFactory.createXMLEventReader(input);

    }
    
    
    /**
     * Method to get the text in next tag matching the tag parameter. 
     * 
     * Note: This method is is currently functioning incorrect. It only takes 
     * the first token in the text between start and end element. After this,
     * html elements need be removed. Does not cause errors. will be fixed in v2.
     * 
     * @param tag 
     * @return a string containing the text between the sent tag parameter. returns an empty string if not found.
     */
    public String getNextTextByTag(RSSFEEDTAGS tag) {
        
        //A String to return text of tag and a boolean for validation
        String textString = "";
        boolean isValidElement = false;
        
        try {
            //While there is another item to parse
            while (xmlEventReader.hasNext()) {
                //get the next event
                XMLEvent event = xmlEventReader.nextEvent();

                //If we are at the start of an element check for valid elementname
                if (event.isStartElement()) 
                {
                        //Get the element name
                        StartElement startElement = event.asStartElement();
                        String elementName = startElement.getName().toString();

                        //Check that it maches the tag requested
                        if(elementName.equalsIgnoreCase(tag.toString()))                   
                        {
                            isValidElement = true;
                        }
                        else
                        {
                            isValidElement = false;
                        }

                   }
                
                //If the event is charaters and we are in a valid element
                if (event.isCharacters()&& isValidElement) 
                {
                    //get the characters and check if its empty white space
                    Characters text = event.asCharacters();
                    if (!text.isWhiteSpace()) 
                    {     
                        //return the text between tag
                        textString = text.getData();
                        return textString;
                    }

                }

            }

        } catch (FactoryConfigurationError | XMLStreamException ex) {
            Logger.getLogger(RssFeedStreamParser.class.getName()).log(Level.SEVERE, null, ex);
        } 
        //Element was not found
        return "";
    }
    

    /**
     * method to close the stream and set to null
     * 
     */
    public void closeStream() 
    {
        try 
        {
            if(xmlEventReader != null)
            xmlEventReader.close();
            
            if(input != null)
            input.close();
            
            xmlEventReader = null;
            input = null;

        } catch (XMLStreamException | IOException ex) {
            Logger.getLogger(RssFeedStreamParser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    


    
    

}